:- ensure_loaded([transitions_alice]).

shuffle(_,[],_).
shuffle(State,Options,[Elem|List]) :-
    randElem(State,Options, Elem),
    remove(Options, Elem, NewOptions),
    shuffle(State,NewOptions,List),
    !.

randElem(_,[],_) :- !, fail.
randElem(_,[Elem|[]], Elem) :- !.
randElem(State,List, Elem) :-
    random(X),
    element(Elem, List),
    transition(State, Elem, ProbFrom, ProbTo),
    X >= ProbFrom,
    X =< ProbTo.
randElem(State,List,Elem) :-
    randElem(State,List,Elem).

element(_,[]) :- !, fail.
element(X,[X|_]).
element(X,[_|T]) :-
    element(X,T).

remove([],_,[]) :- !.
remove([X|T],X,L1) :- !, remove(T,X,L1).
remove([H|T],X,[H|L1]) :- remove(T,X,L1).

path(Path, MaxLength, Win) :-
    length(Path, MaxLength),
    certifyList(['START'|Path],Win).

certifyList([Win|_],Win).
certifyList([H1,H2|T],Win) :-
    createTransList(H1, List),
    shuffle(H1, List, ShuffledList),
    element(H2, ShuffledList),
    certifyList([H2|T], Win).

createTransList(State, List) :-
    createTransList(State, List, 0.000000000).
createTransList(_,[],ProbTotal) :-
    ProbTotal >= 0.999990000. /**Due to float round errors**/
createTransList(State, [H|T], ProbTotal) :-
    transition(State, H, ProbTotal, ProbTo),
    createTransList(State, T, ProbTo).

formatFull([]).
formatFull([H|T]) :-
    nonvar(H),
    format(H),
    formatFull(T).
formatFull([H|_]) :-
    var(H).

pathPrint(Path, MaxLength, Win) :-
    get_time(TimeStart),
    path(Path, MaxLength, Win),
    get_time(TimeEnd),
    formatFull(Path),
    TimeElapsed is TimeEnd - TimeStart,
    format("\n---TIME ELAPSED: "),
    format(TimeElapsed).

